package com.shangxia.monomer.study.math.formula;

/**
 * @author zhouya38158
 * @Package com.shangxia.monomer.study.math
 * @date 2021/7/22 9:14
 */
public class HaversineFormula {
    /**
     * 半正矢公式;
     * 求球面两点距离
     */
    // Radius of sphere on which the points are, in this case Earth.
    private static final double SPHERE_RADIUS_IN_KM = 6372.8;

    public static double findHaversineDistance(double latA, double longA, double latB, double longB) {
        if (!isValidLatitude(latA)
                || !isValidLatitude(latB)
                || !isValidLongitude(longA)
                || !isValidLongitude(longB)) {
            throw new IllegalArgumentException();
        }

        // Calculate the latitude and longitude differences
        double latitudeDiff = Math.toRadians(latB - latA);
        double longitudeDiff = Math.toRadians(longB - longA);

        double latitudeA = Math.toRadians(latA);
        double latitudeB = Math.toRadians(latB);

        // Calculating the distance as per haversine formula
        double a = Math.pow(Math.sin(latitudeDiff / 2), 2)
                + Math.pow(Math.sin(longitudeDiff / 2), 2) * Math.cos(latitudeA) * Math.cos(latitudeB);
        double c = 2 * Math.asin(Math.sqrt(a));
        return SPHERE_RADIUS_IN_KM * c;
    }

    // Check for valid latitude value
    private static boolean isValidLatitude(double latitude) {
        return latitude >= -90 && latitude <= 90;
    }

    // Check for valid longitude value
    private static boolean isValidLongitude(double longitude) {
        return longitude >= -180 && longitude <= 180;
    }
}
